// *****************************************************************************
// *****************************************************************************
// Copyright 2012 - 2014, Cadence Design Systems
//
// This  file  is  part  of  the  Cadence  LEF/DEF  Open   Source
// Distribution,  Product Version 5.8.
//
// Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
//    implied. See the License for the specific language governing
//    permissions and limitations under the License.
//
// For updates, support, or to become part of the LEF/DEF Community,
// check www.openeda.org for details.
//
//  $Author: dell $
//  $Revision: #1 $
//  $Date: 2020/09/29 $
//  $State:  $
// *****************************************************************************
// *****************************************************************************

#ifndef lefiMisc_h
#define lefiMisc_h

#include <cstdio>
#include <string>
#include <utility>
#include <vector>

#include "lefiKRDefs.hpp"

BEGIN_LEF_PARSER_NAMESPACE

// The different types of items in a geometry list.

struct lefiGeomRect
{
  double xl;
  double yl;
  double xh;
  double yh;
  int colorMask;
};

struct lefiGeomRectIter
{
  double xl;
  double yl;
  double xh;
  double yh;
  double xStart;
  double yStart;
  double xStep;
  double yStep;
  int colorMask;
};

struct lefiGeomPath
{
  int numPoints;
  double* x;
  double* y;
  int colorMask;
};

struct lefiGeomPathIter
{
  int numPoints;
  double* x;
  double* y;
  double xStart;
  double yStart;
  double xStep;
  double yStep;
  int colorMask;
};

struct lefiGeomPolygon
{
  int numPoints;
  double* x;
  double* y;
  int colorMask;
};

struct lefiGeomPolygonIter
{
  int numPoints;
  double* x;
  double* y;
  double xStart;
  double yStart;
  double xStep;
  double yStep;
  int colorMask;
};

enum lefiGeomEnum
{
  lefiGeomUnknown = 0,
  lefiGeomLayerE,
  lefiGeomLayerExceptPgNetE,
  lefiGeomLayerMinSpacingE,
  lefiGeomLayerRuleWidthE,
  lefiGeomWidthE,
  lefiGeomPathE,
  lefiGeomPathIterE,
  lefiGeomRectE,
  lefiGeomRectIterE,
  lefiGeomPolygonE,
  lefiGeomPolygonIterE,
  lefiGeomViaE,
  lefiGeomViaIterE,
  lefiGeomClassE,
  lefiGeomEnd
};

struct lefiGeomVia
{
  char* name;
  double x;
  double y;
  int topMaskNum;
  int cutMaskNum;
  int bottomMaskNum;
};

struct lefiGeomViaIter
{
  char* name;
  double x;
  double y;
  double xStart;
  double yStart;
  double xStep;
  double yStep;
  int topMaskNum;
  int cutMaskNum;
  int bottomMaskNum;
};

class lefiGeometries
{
 public:
  lefiGeometries();
  void Init();

  void Destroy();
  ~lefiGeometries();

  void clear();
  void clearPolyItems();
  void add(void* v, lefiGeomEnum e);
  void addLayer(const char* name);
  void addLayerExceptPgNet();  // 5.7
  void addLayerMinSpacing(double spacing);
  void addLayerRuleWidth(double width);
  void addClass(const char* name);
  void addWidth(double w);
  void addPath(int colorMask);
  void addPathIter(int colorMask);
  /*  pcr 481783 & 560504
   */
  void addRect(int colorMask, double xl, double yl, double xh, double yh);
  void addRectIter(int colorMask, double xl, double yl, double xh, double yh);
  void addPolygon(int colorMask = 0);
  void addPolygonIter(int colorMask);
  void addVia(int viaMasks, double x, double y, const char* name);
  void addViaIter(int viaMasks, double x, double y, const char* name);
  void addStepPattern(double xStart, double yStart, double xStep, double yStep);
  void startList(double x, double y);
  void addToList(double x, double y);

  int numItems() const;
  lefiGeomEnum itemType(int index) const;
  lefiGeomRect* getRect(int index) const;
  lefiGeomRectIter* getRectIter(int index) const;
  lefiGeomPath* getPath(int index) const;
  lefiGeomPathIter* getPathIter(int index) const;
  int hasLayerExceptPgNet(int index) const;  // 5.7
  char* getLayer(int index) const;
  double getLayerMinSpacing(int index) const;
  double getLayerRuleWidth(int index) const;
  double getWidth(int index) const;
  lefiGeomPolygon* getPolygon(int index) const;
  lefiGeomPolygonIter* getPolygonIter(int index) const;
  char* getClass(int index) const;
  lefiGeomVia* getVia(int index) const;
  lefiGeomViaIter* getViaIter(int index) const;

  void print(FILE* f) const;

 protected:
  int numItems_;
  int itemsAllocated_;
  lefiGeomEnum* itemType_;
  void** items_;

  int numPoints_;
  int pointsAllocated_;
  double* x_;
  double* y_;

  double xStart_;
  double yStart_;
  double xStep_;
  double yStep_;
};

class lefiSpacing
{
 public:
  lefiSpacing();
  void Init();

  void Destroy();
  ~lefiSpacing();

  lefiSpacing* clone();

  void set(const char* name1, const char* name2, double num, int hasStack);

  int hasStack() const;

  const char* name1() const;
  const char* name2() const;
  double distance() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int name1Size_;
  int name2Size_;
  char* name1_;
  char* name2_;
  double distance_;
  int hasStack_;
};

class lefiIRDrop
{
 public:
  lefiIRDrop();
  void Init();

  void Destroy();
  ~lefiIRDrop();

  void clear();
  void setTableName(const char* name);
  void setValues(double name1, double name2);

  const char* name() const;
  double value1(int index) const;
  double value2(int index) const;

  int numValues() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int nameSize_;
  int value1Size_;
  int value2Size_;
  int numValues_;
  int valuesAllocated_;
  char* name_;
  double* value1_;
  double* value2_;
};

class lefiMinFeature
{
 public:
  lefiMinFeature();
  void Init();

  void Destroy();
  ~lefiMinFeature();

  void set(double one, double two);

  double one() const;
  double two() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  double one_;
  double two_;
};

class lefiSite
{
 public:
  lefiSite();
  void Init();

  void Destroy();
  ~lefiSite();

  void setName(const char* name);
  void setClass(const char* cls);
  void setSize(double x, double y);
  void setXSymmetry();
  void setYSymmetry();
  void set90Symmetry();
  void addRowPattern(const char* name, int orient);
  std::vector<std::pair<std::string, std::string>> getRowPatterns() const;

  const char* name() const;
  int hasClass() const;
  const char* siteClass() const;
  double sizeX() const;
  double sizeY() const;
  int hasSize() const;
  int hasXSymmetry() const;
  int hasYSymmetry() const;
  int has90Symmetry() const;
  int hasRowPattern() const;             // 5.6
  int numSites() const;                  // 5.6
  char* siteName(int index) const;       // 5.6
  int siteOrient(int index) const;       // 5.6
  char* siteOrientStr(int index) const;  // 5.6

  // Debug print
  void print(FILE* f) const;

 protected:
  int nameSize_;
  char* name_;
  int hasClass_;
  char siteClass_[8];
  double sizeX_;
  double sizeY_;
  int hasSize_;
  int symmetry_;  // bit 0-x   bit 1-y   bit 2-90

  int numRowPattern_;  // 5.6 ROWPATTERN
  int rowPatternAllocated_;
  char** siteNames_;
  int* siteOrients_;
};

class lefiSitePattern
{
 public:
  lefiSitePattern();
  void Init();

  void Destroy();
  ~lefiSitePattern();

  void set(const char* name,
           double x,
           double y,
           int orient,
           double xStart,
           double yStart,
           double xStep,
           double yStep);

  const char* name() const;
  int orient() const;
  const char* orientStr() const;
  double x() const;
  double y() const;
  int hasStepPattern() const;  // 5.6
  double xStart() const;
  double yStart() const;
  double xStep() const;
  double yStep() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int nameSize_;
  char* name_;
  int orient_;
  double x_;
  double y_;
  double xStart_;
  double yStart_;
  double xStep_;
  double yStep_;
};

class lefiTrackPattern
{
 public:
  lefiTrackPattern();
  void Init();

  void Destroy();
  ~lefiTrackPattern();

  void clear();
  void set(const char* name, double start, int numTracks, double space);
  void addLayer(const char* name);

  const char* name() const;
  double start() const;
  int numTracks() const;
  double space() const;

  int numLayers() const;
  const char* layerName(int index) const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int nameSize_;
  char* name_;
  double start_;
  int numTracks_;
  double space_;

  int numLayers_;
  int layerAllocated_;
  char** layerNames_;
};

class lefiGcellPattern
{
 public:
  lefiGcellPattern();
  void Init();

  void Destroy();
  ~lefiGcellPattern();

  void set(const char* name, double start, int numCRs, double space);

  const char* name() const;
  double start() const;
  int numCRs() const;
  double space() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int nameSize_;
  char* name_;
  double start_;
  int numCRs_;
  double space_;
};

class lefiUseMinSpacing
{
 public:
  lefiUseMinSpacing();
  void Init();

  void Destroy();
  ~lefiUseMinSpacing();

  void set(const char* name, int value);

  const char* name() const;
  int value() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  char* name_;
  int value_;
};

// 5.5 for Maximum Stacked-via rule
class lefiMaxStackVia
{
 public:
  lefiMaxStackVia();
  void Init();

  void Destroy();
  ~lefiMaxStackVia();

  void clear();
  void setMaxStackVia(int value);
  void setMaxStackViaRange(const char* bottomLayer, const char* topLayer);

  int maxStackVia() const;
  int hasMaxStackViaRange() const;
  const char* maxStackViaBottomLayer() const;
  const char* maxStackViaTopLayer() const;

  // Debug print
  void print(FILE* f) const;

 protected:
  int value_;
  int hasRange_;
  char* bottomLayer_;
  char* topLayer_;
};

END_LEF_PARSER_NAMESPACE

#endif
